package org.example.constangt;


import io.swagger.annotations.ApiResponse;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.example.common.exception.BusinessException;
import org.example.dto.TOperateLog;
import org.example.log.Log;
import org.example.mapper.LogDao;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;

@Component
@Aspect
public class LogAspect {
    @Resource
    private LogDao logDao;

    /**
     * 操作日志切入点：表示在注解位置切入代码
     * 括号内写自定义注解完全限定名
     */
    @Pointcut("@annotation(org.example.log.Log)")
    public void operLogPoinCut() {
    }

    /**
     * 目标方法执行成功并返回后执行
     *
     * @param joinPoint  目标方法信息对象，可获取目标方法方法名、参数等
     * @param keys      目标方法返回值，可以将目标方法返回值传递给切面方法这个参数
     */
    @AfterReturning(value = "operLogPoinCut()", returning = "keys")// 切入点表达式；表示将目标方法返回值绑定到切面方法参数keys
    public void saveOperLog(JoinPoint joinPoint, Object keys) {
        // 获取 RequestAttributes
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        // 从 RequestAttributes 中获取 HttpServletRequest 的信息（可获取请求方法，URL，IP等）
        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);

        // 创建一个 TOperateLog 对象用于保存操作日志
        TOperateLog operateLog = new TOperateLog();
        try {
            // 通过反射机制获取切面织入点处的方法信息
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            // 获取切入点所在的方法对象
            Method method = signature.getMethod();
            // 获取方法上的 OperateLog 注解
            Log opLog = method.getAnnotation(Log.class);
            if (opLog != null) {
                // 获取注解中的操作模块、操作类型和操作描述信息，并设置到操作日志对象中
                String operModul = opLog.operModul(); // 获取操作模块
                SysLogType operType = opLog.methodType(); // 获取操作类型
                String operDesc = opLog.description(); // 获取操作描述

                operateLog.setModelName(operModul); // 设置业务名称
//                operateLog.setRowType(operType.getTypeName()); // 设置操作类型
                operateLog.setOperateContent(operDesc+request.getRequestURL()+request.getParameter("id")); // 设置操作记录
            }

            operateLog.setOperateTime(new Date());
            operateLog.setUnitId("111");
            operateLog.setOperateUser("111");
            operateLog.setOperateAccount("111");

            // 调用 platformFeignClient 的 add 方法，向日志服务中添加操作日志（根据场景实际进行持久化）
            Boolean add = logDao.insertLog(operateLog);

            // 判断日志服务添加操作是否成功
            if (!add) {
                throw new BusinessException("feign调用日志服务失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
